﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Xml;
using Microsoft.SharePoint;
using Repo.Helpers;
using SPRepoDemo.Web.Entities;

namespace SPRepoDemo.Web.Helpers
{
    public class ListHelper
    {
        public static SPList CreateList(SPWeb web, ListToCreate listToCreate)
        {
            if (!string.IsNullOrEmpty(listToCreate.Definition))
            {
                LoggingHelper.VerboseLog("Creating list based on definition " + listToCreate.Definition);
                if (listToCreate.Definition == "Document library")
                {
                    const SPListTemplateType documentLibrary = SPListTemplateType.DocumentLibrary;
                    return Createlist(web, listToCreate.Title, documentLibrary);
                }
                var listTemplate = GetListTemplates(web).FirstOrDefault(x => x.Name == listToCreate.Definition);
                if (listTemplate != null)
                {
                    return Createlist(web, listToCreate.Title, listTemplate);
                }
                LoggingHelper.VerboseLog("List Template " + listToCreate.Definition + " does not exists");
            }
            else if (!string.IsNullOrEmpty(listToCreate.ContentType))
            {
                LoggingHelper.VerboseLog("Creating list based on content type " + listToCreate.ContentType);
                return CreateListForContentType(web, listToCreate);
            }
            return null;
        }

        private static void CreateListForListTemplate(SPWeb web, string listTitle, string listTemplateName)
        {
            var listTemplate =
                web.Site.RootWeb.ListTemplates.Cast<SPListTemplate>().FirstOrDefault(
                    x => x.Name == listTemplateName);
            if (listTemplate != null)
            {
                Createlist(web, listTitle, listTemplate);
            }
        }

        private static SPList Createlist(SPWeb web, string listTitle, SPListTemplate listTemplate)
        {
            if (web.Lists.TryGetList(listTitle) == null)
            {
                web.AllowUnsafeUpdates = true;
                LoggingHelper.VerboseLog("Creating list " + listTitle);
                var id = web.Lists.Add(listTitle, string.Empty, listTemplate);
                web.Update();
                web.AllowUnsafeUpdates = false;
                return web.Lists[id];
            }
            return null;
        }

        private static SPList Createlist(SPWeb web, string listTitle, SPListTemplateType listTemplateType)
        {
            if (web.Lists.TryGetList(listTitle) == null)
            {
                web.AllowUnsafeUpdates = true;
                LoggingHelper.VerboseLog("Creating list " + listTitle);
                var id = web.Lists.Add(listTitle, string.Empty, listTemplateType);
                web.Update();
                web.AllowUnsafeUpdates = false;
                return web.Lists[id];
            }
            return null;
        }

        private static SPList CreateListForContentType(SPWeb web, ListToCreate listToCreate)
        {
            var listTitle = listToCreate.Title;
            LoggingHelper.VerboseLog("Seeing if the list " + listToCreate.Title + " already exists");
            if (web.Lists.TryGetList(listTitle) == null)
            {
                try
                {
                    web.AllowUnsafeUpdates = true;
                    LoggingHelper.VerboseLog("Getting Custom List Template");
                    var listTemplate =
                        web.Site.RootWeb.ListTemplates.Cast<SPListTemplate>().FirstOrDefault(
                            x => x.Name == "Custom List");
                    LoggingHelper.VerboseLog("Creating a Custom List");
                    web.Lists.Add(listTitle, string.Empty, listTemplate);
                    LoggingHelper.VerboseLog("Getting new list");
                    var thisNewList = web.Lists[listTitle];
                    LoggingHelper.VerboseLog("Getting content type " + listToCreate.ContentType);
                    var contentType =
                        web.Site.RootWeb.ContentTypes.Cast<SPContentType>().FirstOrDefault(
                            ct => ct.Name == listToCreate.ContentType);
                    if (contentType != null)
                    {
                        LoggingHelper.VerboseLog("Adding content type " + listToCreate.ContentType + " to list");
                        thisNewList.ContentTypes.Add(contentType);
                        LoggingHelper.VerboseLog("removing Item content type from list");
                        var itemContentType = thisNewList.ContentTypes.Cast<SPContentType>().Where(x => x.Name == "Item").FirstOrDefault();
                        thisNewList.ContentTypes.Delete(itemContentType.Id);
                        LoggingHelper.VerboseLog("Updating list");
                        thisNewList.Update();
                    }
                    LoggingHelper.VerboseLog("Updating web");
                    web.Update();
                    return thisNewList;
                }
                catch (Exception exception)
                {
                    LoggingHelper.ErrorLog(exception);
                }
                finally
                {
                    web.AllowUnsafeUpdates = false;
                }
            }
            return null;
        }

        public static SPList GetDocumentLibraryAndCreateIfNotExists(SPWeb web, string listTitle)
        {
            return GetListAndCreateIfNotExists(web, listTitle, web.ListTemplates["Document Library"]);
        }

        public static SPList GetListAndCreateIfNotExists(SPWeb web, string listTitle, SPListTemplate listTemplate)
        {
            var list = web.Lists.TryGetList(listTitle);
            if (list == null)
            {
                web.AllowUnsafeUpdates = true;
                web.Lists.Add(listTitle, string.Empty, listTemplate);
                web.Update();
                web.AllowUnsafeUpdates = false;
                list = web.Lists.TryGetList(listTitle);
            }
            return list;
        }

        public static void CreateDefaultLists(SPWeb web)
        {
            foreach (SPListTemplate listTemplate in GetListTemplates(web).Where(x => (int)x.Type >= 10000))
            {
                if (listTemplate.BaseType == SPBaseType.GenericList
                    && listTemplate.CategoryType == SPListCategoryType.CustomLists)
                {
                    var title = listTemplate.Name;
                    if (title.IndexOf("List") != -1)
                    {
                        title = title.Replace("List", "");
                    }
                    if (title.IndexOf("Definition") != -1)
                    {
                        title = title.Replace("Definition", "");
                    }
                    title = title.Trim();
                    if (web.Site.RootWeb.Lists.TryGetList(title) == null)
                    {
                        Createlist(web, title, listTemplate);
                    }
                }
            }
        }

        public static IEnumerable<SPListTemplate> GetListTemplates(SPWeb web)
        {
            return web.Site.RootWeb.ListTemplates.Cast<SPListTemplate>().Where(
                x => x.BaseType == SPBaseType.GenericList && x.CategoryType == SPListCategoryType.CustomLists);
        }

        public static List<ListToCreate> GetListsToCreate(SPSite site, string xmlLocation)
        {
            var listsToCreate = new List<ListToCreate>();
            WebResponse response = null;
            try
            {
                LoggingHelper.VerboseLog("Getting lists from " + site.Url + xmlLocation);
                WebRequest request = WebRequest.Create(site.Url + xmlLocation);
                var xml = new XmlDocument();
                LoggingHelper.VerboseLog("Loading xml with default credentials");
                request.Credentials = CredentialCache.DefaultCredentials;
                response = request.GetResponse();
                if (response != null)
                {
                    using (var reader = new StreamReader(response.GetResponseStream()))
                    {
                        LoggingHelper.VerboseLog("Loading xml into Xml document");
                        //contents = reader.ReadToEnd();
                        xml.Load(reader);
                        XmlNodeList elemList = xml.GetElementsByTagName("list");
                        LoggingHelper.VerboseLog("Looping through list elements in xml");
                        for (int i = 0; i < elemList.Count; i++)
                        {
                            var listToCreate = new ListToCreate();
                            if (elemList[i].Attributes != null)
                            {
                                LoggingHelper.VerboseLog("setting properties of entity 'ListToCreate' based on attributes of xml");
                                var properties = typeof(ListToCreate).GetProperties();
                                foreach (var propertyInfo in properties)
                                {
                                    if (elemList[i].Attributes.GetNamedItem(propertyInfo.Name) != null)
                                    {
                                        LoggingHelper.VerboseLog("Setting value of " + propertyInfo.Name + " to " + elemList[i].Attributes[propertyInfo.Name].Value);
                                        propertyInfo.SetValue(listToCreate, elemList[i].Attributes[propertyInfo.Name].Value, null);
                                    }
                                }
                                listsToCreate.Add(listToCreate);
                            }
                        }
                    }
                }
            }
            finally
            {
                if (response != null)
                {
                    response.Close();
                }
            }
            return listsToCreate;
        }

    }
}
